﻿using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
using System.Reflection;
using SBlogCore.Common.FriendlyException;
using SBlogCore.Common.DatabaseAccessor.Entitys;
using SBlogCore.Common.App;

namespace SBlogCore.Common.DatabaseAccessor
{
    [SkipScan]
    public class GlobalDbContext : DbContext
    {
        public GlobalDbContext(DbContextOptions<GlobalDbContext> options)
        : base(options)
        {
        }
        /// <summary>
        /// 查找配置类
        /// </summary>
        /// <param name="modelBuilder"></param>
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            var assembly = Assembly.Load(new AssemblyName("SBlogCore.Entitys"));
            if (assembly==null)
            {
                throw SBlogCoreException.Say($"需绑定实体类库！");
            }
            //指定配置类所在的程序集
            modelBuilder.ApplyConfigurationsFromAssembly(assembly);
            //查找所有继承该接口的实体类
            var list = assembly.GetTypes().Where(c =>c.IsAssignableTo(typeof(IBaseEntity))).ToList();
            //判断是否存在该实体，不存在则加入
            var needReg = list.Where(w => modelBuilder.Model.FindEntityType(w)==null);
            foreach (var type in needReg)
            {
                modelBuilder.Model.AddEntityType(type);
            }
            if (list.Any())
            {
                list.ForEach(t =>
                {
                    if (t.GetProperties().Any(w=>w.Name== "IsDeleted"))
                    {
                        DeleteQueryFilter(modelBuilder, t);
                    }
                });
            }
            //排除表
            modelBuilder.Ignore("DbFieldManager");
        }
        /// <summary>
        /// 过滤
        /// </summary>
        /// <param name="modelBuilder"></param>
        /// <param name="t"></param>
        private static void DeleteQueryFilter(ModelBuilder modelBuilder, Type t)
        {
            var parameter = Expression.Parameter(t, "u");
            var properName = Expression.Constant("IsDeleted");
            var propertyValue = Expression.Constant(false);

            var expressionBody =
                Expression.Equal(Expression.Call(typeof(EF), nameof(EF.Property), new[] {typeof(bool)}, parameter, properName),
                    propertyValue);
            var expression = Expression.Lambda(expressionBody, parameter);
            modelBuilder.Entity(t).HasQueryFilter(expression);
        }
        
        /// <summary>
        /// 重新保存逻辑
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
        {
            BeforeSaveChangeEvent();
            return base.SaveChangesAsync(cancellationToken);
        }

        /// <summary>
        /// 重新保存逻辑
        /// </summary>
        /// <returns></returns>
        public override int SaveChanges()
        {
            BeforeSaveChangeEvent();
            return base.SaveChanges();
        }
        /// <summary>
        /// 保存之前
        /// </summary>
        private void BeforeSaveChangeEvent()
        {
            var deleteEntity = ChangeTracker.Entries().Where(w => w.State == EntityState.Deleted && w.Entity is DeleteEntity);
            var userToken = AppBase.GetJwtUser();
            foreach (var e in deleteEntity)
            {
                var deEntity = ((DeleteEntity) e.Entity);
                deEntity.IsDeleted = true;
                if (userToken != null)
                {
                    deEntity.UpdatedUserId =  userToken.Uid;
                }
                deEntity.UpdatedTime=DateTimeOffset.Now;
                e.State = EntityState.Modified;
            }
        }

    }
}
